<!-- components/DocumentFormDesigner.vue -->
<template>
  <div class="form-designer">
    <el-row :gutter="20">
      <!-- 组件面板 -->
      <el-col :span="6">
        <div class="components-panel">
          <h3>表单组件</h3>
          <div class="components-list">
            <div
              v-for="component in componentTypes"
              :key="component.type"
              class="component-item"
              draggable="true"
              @dragstart="(event) => onDragStart(event, component)"
            >
              <el-icon><component :is="component.icon" /></el-icon>
              <span>{{ component.name }}</span>
            </div>
          </div>
        </div>
      </el-col>

      <!-- 设计画布 -->
      <el-col :span="12">
        <div class="design-canvas" @drop="onDrop" @dragover="onDragOver">
          <div v-if="formSchema.length === 0" class="empty-canvas">
            <el-icon><Plus /></el-icon>
            <p>拖拽组件到此区域开始设计表单</p>
          </div>

          <draggable
            v-model="formSchema"
            item-key="id"
            class="form-fields"
            ghost-class="ghost"
            @start="drag = true"
            @end="drag = false"
          >
            <template #item="{ element, index }">
              <div
                class="form-field"
                :class="{ active: selectedField?.id === element.id }"
                @click="selectField(element)"
              >
                <div class="field-header">
                  <span class="field-label">{{ element.label }}</span>
                  <el-button type="danger" link size="small" @click="removeField(index)">
                    <el-icon><Delete /></el-icon>
                  </el-button>
                </div>

                <!-- 动态渲染组件预览 -->
                <component-preview :field="element" :value="formData[element.model]" />
              </div>
            </template>
          </draggable>
        </div>
      </el-col>

      <!-- 属性配置面板 -->
      <el-col :span="6">
        <div class="properties-panel" v-if="selectedField">
          <h3>属性配置</h3>
          <el-form :model="selectedField" label-width="80px">
            <el-form-item label="字段标签">
              <el-input v-model="selectedField.label" />
            </el-form-item>

            <el-form-item label="字段名">
              <el-input v-model="selectedField.model" />
            </el-form-item>

            <el-form-item
              label="占位文本"
              v-if="!['radio', 'checkbox'].includes(selectedField.type)"
            >
              <el-input v-model="selectedField.placeholder" />
            </el-form-item>

            <el-form-item label="是否必填">
              <el-switch v-model="selectedField.required" />
            </el-form-item>

            <!-- 选项配置 -->
            <el-form-item
              label="选项"
              v-if="['select', 'radio', 'checkbox'].includes(selectedField.type)"
            >
              <div
                v-for="(option, optIndex) in selectedField.options"
                :key="optIndex"
                class="option-item"
              >
                <el-input
                  v-model="option.label"
                  placeholder="选项标签"
                  style="margin-bottom: 5px"
                />
                <el-input v-model="option.value" placeholder="选项值" />
                <el-button type="danger" link @click="removeOption(selectedField, optIndex)">
                  <el-icon><Delete /></el-icon>
                </el-button>
              </div>
              <el-button @click="addOption(selectedField)" type="primary" link>
                添加选项
              </el-button>
            </el-form-item>
          </el-form>
        </div>
        <div v-else class="properties-panel">
          <h3>属性配置</h3>
          <p class="no-selection">请选择表单字段进行配置</p>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script setup>
import { ref, reactive, markRaw, h } from 'vue'
import draggable from 'vuedraggable'
import { Document, Edit, Select, Checked, Calendar, Plus, Delete } from '@element-plus/icons-vue'

// 使用 markRaw 包装组件，防止它们被转换为响应式对象
const rawIcons = {
  Document: markRaw(Document),
  Edit: markRaw(Edit),
  Select: markRaw(Select),
  Checked: markRaw(Checked),
  Calendar: markRaw(Calendar),
  Plus: markRaw(Plus),
  Delete: markRaw(Delete),
}

// 组件预览子组件
const ComponentPreview = {
  props: ['field', 'value'],
  setup(props) {
    return () => {
      const { field } = props
      switch (field.type) {
        case 'input':
          return h('el-input', {
            placeholder: field.placeholder,
            modelValue: props.value,
            disabled: true,
          })
        case 'textarea':
          return h('el-input', {
            type: 'textarea',
            placeholder: field.placeholder,
            modelValue: props.value,
            disabled: true,
          })
        case 'select':
          return h(
            'el-select',
            {
              placeholder: field.placeholder,
              modelValue: props.value,
              disabled: true,
            },
            () =>
              field.options?.map((opt) =>
                h('el-option', {
                  label: opt.label,
                  value: opt.value,
                }),
              ),
          )
        case 'radio':
          return h(
            'el-radio-group',
            {
              modelValue: props.value,
              disabled: true,
            },
            () =>
              field.options?.map((opt) =>
                h(
                  'el-radio',
                  {
                    label: opt.value,
                  },
                  () => opt.label,
                ),
              ),
          )
        case 'checkbox':
          return h(
            'el-checkbox-group',
            {
              modelValue: props.value,
              disabled: true,
            },
            () =>
              field.options?.map((opt) =>
                h(
                  'el-checkbox',
                  {
                    label: opt.value,
                  },
                  () => opt.label,
                ),
              ),
          )
        case 'date':
          return h('el-date-picker', {
            placeholder: field.placeholder,
            modelValue: props.value,
            disabled: true,
          })
        default:
          return h('div', '未知组件')
      }
    }
  },
}

// 可用的组件类型
const componentTypes = ref([
  { type: 'input', name: '单行文本', icon: rawIcons.Document },
  { type: 'textarea', name: '多行文本', icon: rawIcons.Edit },
  { type: 'select', name: '下拉选择', icon: rawIcons.Select },
  { type: 'radio', name: '单选框', icon: rawIcons.Checked },
  { type: 'checkbox', name: '多选框', icon: rawIcons.Checked },
  { type: 'date', name: '日期选择', icon: rawIcons.Calendar },
])

// 表单结构
const formSchema = ref([])
// 表单数据
const formData = ref({})
// 当前选中的字段
const selectedField = ref(null)
// 拖拽状态
const drag = ref(false)

// 拖拽开始
const onDragStart = (event, component) => {
  event.dataTransfer.setData('componentType', component.type)
}

// 拖拽经过
const onDragOver = (event) => {
  event.preventDefault()
}

// 拖拽放下
const onDrop = (event) => {
  event.preventDefault()
  const componentType = event.dataTransfer.getData('componentType')
  addNewField(componentType)
}

// 添加新字段
const addNewField = (type) => {
  const newField = {
    id: Date.now().toString(),
    type: type,
    label: `字段${formSchema.value.length + 1}`,
    model: `field${formSchema.value.length + 1}`,
    placeholder: `请输入${type === 'input' ? '文本' : '内容'}`,
    required: false,
    options:
      type === 'select' || type === 'radio' || type === 'checkbox'
        ? [{ label: '选项1', value: 'option1' }]
        : undefined,
  }
  formSchema.value.push(newField)
  selectField(newField)
}

// 选择字段
const selectField = (field) => {
  selectedField.value = field
}

// 移除字段
const removeField = (index) => {
  if (selectedField.value?.id === formSchema.value[index].id) {
    selectedField.value = null
  }
  formSchema.value.splice(index, 1)
}

// 添加选项
const addOption = (field) => {
  if (!field.options) {
    field.options = []
  }
  field.options.push({
    label: `选项${field.options.length + 1}`,
    value: `option${field.options.length + 1}`,
  })
}

// 移除选项
const removeOption = (field, index) => {
  field.options.splice(index, 1)
}

// 暴露方法给父组件
defineExpose({
  getFormSchema: () => formSchema.value,
  setFormSchema: (schema) => {
    formSchema.value = schema || []
  },
})
</script>

<style scoped>
.form-designer {
  height: 600px;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
}

.components-panel,
.design-canvas,
.properties-panel {
  height: 100%;
  padding: 16px;
  border: 1px solid #e4e7ed;
  background: #fafafa;
}

.components-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.component-item {
  padding: 12px;
  background: white;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  cursor: move;
  display: flex;
  align-items: center;
  gap: 8px;
}

.component-item:hover {
  border-color: #409eff;
}

.design-canvas {
  min-height: 400px;
  background: white;
}

.empty-canvas {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #909399;
}

.form-fields {
  min-height: 100px;
}

.form-field {
  padding: 12px;
  margin-bottom: 8px;
  background: white;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  cursor: pointer;
}

.form-field:hover {
  border-color: #409eff;
}

.form-field.active {
  border-color: #409eff;
  box-shadow: 0 0 0 2px rgba(64, 158, 255, 0.2);
}

.field-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}

.field-label {
  font-weight: bold;
}

.option-item {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
}

.no-selection {
  text-align: center;
  color: #909399;
  margin-top: 50%;
}

.ghost {
  opacity: 0.5;
}
</style>
